package znet

import (
	"bytes"
	"encoding/binary"
	"errors"
	"fmt"
	"io"
	"net"
	"zinx-learn/utils"
	"zinx-learn/ziface"
)

type DataPack struct {
	DataHeadLen uint32 // 头字节长度  //Id uint32(4字节) +  DataLen uint32(4字节)
}

func (d DataPack) Pack(msg ziface.IMessage) ([]byte, error) {
	// 将 ID 和 DataLen 放在头部 ID(4字节) | DataLen(4字节) | data
	// 创建一个字节缓冲区
	buffer := bytes.NewBuffer([]byte{})
	// 写入id
	err := binary.Write(buffer, binary.LittleEndian, msg.GetMsgId())
	if err != nil {
		return nil, err
	}
	// 写入数据长度
	err = binary.Write(buffer, binary.LittleEndian, msg.GetDataLen())
	if err != nil {
		return nil, err
	}
	// 写入数据
	err = binary.Write(buffer, binary.LittleEndian, msg.GetData())
	if err != nil {
		return nil, err
	}
	return buffer.Bytes(), nil
}

// Unpack 拆包方法
func (d DataPack) Unpack(bs []byte) (ziface.IMessage, error) {
	buffer := bytes.NewReader(bs)
	msg := &Message{}
	err := binary.Read(buffer, binary.LittleEndian, &msg.ID)
	if err != nil {
		return nil, err
	}
	err = binary.Read(buffer, binary.LittleEndian, &msg.DataLen)
	if err != nil {
		return nil, err
	}

	// 超出最大的包的数据长度
	if utils.GlobalObject.MaxPacketSize > 0 && utils.GlobalObject.MaxPacketSize < msg.DataLen {
		return nil, errors.New("msg.DataLen 超出 utils.GlobalObject.MaxPacketSize ")
	}
	//不需要再次读取数据 只需要获取数据的长度 之后再从缓存中读取
	return msg, nil
}

func (d DataPack) ConnToMsg(conn *net.TCPConn) (ziface.IMessage, error) {
	headerBuff := make([]byte, d.DataHeadLen)
	_, err := io.ReadFull(conn, headerBuff)
	if err == io.EOF {
		fmt.Println("read end")
		return nil, err
	}
	if err != nil {
		fmt.Println("read HeadBuff error", err.Error())
		return nil, err
	}
	message, err := d.Unpack(headerBuff)
	if err != nil {
		fmt.Println("unpack message error", err.Error())
		return nil, err
	}
	data := make([]byte, message.GetDataLen())
	_, err = io.ReadFull(conn, data)
	if err != nil {
		fmt.Println("read buf error", err.Error())
		return nil, err
	}
	message.SetData(data)
	return message, nil
}

func NewDataPack() *DataPack {
	return &DataPack{
		DataHeadLen: 8,
	}
}
